﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;

namespace Galaktika.BI.Silverlight.ClientApp
{
    public class LayoutControl : UserControl
    {
        public LayoutControl()
        {
            base.Content = new ScrollViewer() 
            { 
                BorderThickness = new Thickness(), 
                VerticalScrollBarVisibility = ScrollBarVisibility.Auto, 
                HorizontalScrollBarVisibility = ScrollBarVisibility.Auto 
                //VerticalContentAlignment = VerticalAlignment.Stretch, 
                //HorizontalContentAlignment = HorizontalAlignment.Stretch 
            };
        }

        private Dictionary<string, LayoutControlItem> m_Items = new Dictionary<string, LayoutControlItem>();
        public void LoadLayout(string xml, bool trimBottom)
        {
            m_Items.Clear();
            LayoutContainer layout = LayoutParser.Parse(xml);
            GridDescriptor descriptor = GridDescriptor.Create(layout);
            Grid grid = new Grid();
            ((ScrollViewer)base.Content).Content = grid;
            this.ProcessGridDescriptor(grid, null, null, descriptor);
        }

        public void AddElement(UIElement element)
        {
            FrameworkElement fe = element as FrameworkElement;
            if (fe == null) return;
            LayoutControlItem item;
            m_Items.TryGetValue(fe.Name, out item);
            if (item == null) return;

            item.AssignContent(element);
        }

        private void ProcessGridDescriptor(
            Grid parent, 
            RowDefinition parentRow, 
            ColumnDefinition parentColumn, 
            GridDescriptor descriptor)
        {
            if (descriptor.IsGroup)
            {
                this.CreateLayoutGroupElement(parent, parentRow, parentColumn, descriptor);
            }
            else
            {
                if (descriptor.IsLeaf)
                {
                    switch (descriptor.LayoutItem.TypeName)
                    {
                        case LayoutItemTypeName.EmptySpaceItem:
                            this.CreateEmptySpaceItemElement(parent, parentRow, parentColumn, descriptor);
                            break;
                        case LayoutItemTypeName.LayoutControlItem:
                            this.CreateLeafElement(parent, parentRow, parentColumn, descriptor);
                            break;
                        //case LayoutItemTypeName.LayoutGroup:
                        //    this.CreateLayoutGroupElement(parent, parentRow, parentColumn, descriptor);
                        //    break;
                        default:
                            break;
                    }
                }
                else
                {
                    this.CreateLayoutItemElement(parent, parentRow, parentColumn, descriptor);
                }
            }
        }

        private void CreateLeafElement(
            Grid parent,
            RowDefinition parentRow,
            ColumnDefinition parentColumn,
            GridDescriptor descriptor)
        {
            RowDefinition row = parentRow;
            ColumnDefinition col = parentColumn;
            if (parentRow == null)
            {
                row = new RowDefinition();
                col = new ColumnDefinition();
                parent.RowDefinitions.Add(row);
                parent.ColumnDefinitions.Add(col);
            }

            LayoutItemBase lib = descriptor.LayoutItem;
            // max size
            //
            if (lib.MaxSize.Width > 0.0)
            {
                col.MaxWidth = lib.MaxSize.Width;
            }
            if (lib.MaxSize.Height > 0.0)
            {
                row.MaxHeight = lib.MaxSize.Height;
            }
            // min size
            //
            if (lib.MinSize.Width > 0.0)
            {
                col.MinWidth = lib.MinSize.Width;
            }
            if (lib.MinSize.Height > 0.0)
            {
                row.MinHeight = lib.MinSize.Height;
            }

            LayoutControlItem li = new LayoutControlItem(descriptor.LayoutItem);
            parent.Children.Add(li);
            if (!string.IsNullOrEmpty(lib.ControlName))
            {
                m_Items.Add(lib.ControlName, li);
            }
        }

        private void CreateEmptySpaceItemElement(
            Grid parent,
            RowDefinition parentRow,
            ColumnDefinition parentColumn,
            GridDescriptor descriptor)
        {
            // TODO: обработать EmptySpaceItem
            this.CreateLeafElement(parent, parentRow, parentColumn, descriptor);
        }

        private void CreateLayoutItemElement(
            Grid parent,
            RowDefinition parentRow,
            ColumnDefinition parentColumn,
            GridDescriptor descriptor)
        {
            if (descriptor.Children.Count > 0)
            {
                for (int i = 0; i < descriptor.RowCount; i++)
                {
                    parent.RowDefinitions.Add(new RowDefinition());
                }
                for (int i = 0; i < descriptor.ColumnCount; i++)
                {
                    parent.ColumnDefinitions.Add(new ColumnDefinition());
                }

                double[] columnWeights = new double[descriptor.ColumnCount];
                double minColumnWeight = double.MaxValue;
                double[] rowWeights = new double[descriptor.RowCount];
                double minRowHeight = double.MaxValue;

                foreach (GridCellDescriptor child in descriptor.Children)
                {
                    Grid grid = new Grid();
                    Grid.SetColumn(grid, child.ColumnIndex);
                    Grid.SetRow(grid, child.RowIndex);
                    parent.Children.Add(grid);

                    columnWeights[child.ColumnIndex] = child.Bounds.Width;
                    rowWeights[child.RowIndex] = child.Bounds.Height;
                    minColumnWeight = Math.Min(minColumnWeight, child.Bounds.Width);
                    minRowHeight = Math.Min(minRowHeight, child.Bounds.Height);

                    this.ProcessGridDescriptor(
                        grid,
                        parent.RowDefinitions[child.RowIndex],
                        parent.ColumnDefinitions[child.ColumnIndex],
                        child.Child);
                }

                for (int i = 0; i < columnWeights.Length; i++)
                {
                    //if (parent.ColumnDefinitions[i].Width == GridLength.Auto) continue;
                    columnWeights[i] = columnWeights[i] / minColumnWeight;
                    parent.ColumnDefinitions[i].Width = new GridLength(columnWeights[i], GridUnitType.Star);
                }
                for (int i = 0; i < rowWeights.Length; i++)
                {
                    //if (parent.RowDefinitions[i].Height == GridLength.Auto) continue;
                    rowWeights[i] = rowWeights[i] / minRowHeight;
                    parent.RowDefinitions[i].Height = new GridLength(rowWeights[i], GridUnitType.Star);
                }
            }
        }

        private void CreateLayoutGroupElement(
            Grid parent,
            RowDefinition parentRow,
            ColumnDefinition parentColumn,
            GridDescriptor descriptor)
        {
            RowDefinition headerRow = new RowDefinition() ;//{ Height = GridLength.Auto };
            RowDefinition contentRow = new RowDefinition() ;//{ Height = GridLength.Auto };
            ColumnDefinition contentColumn = new ColumnDefinition() ;//{ Width = GridLength.Auto };

            parent.RowDefinitions.Add(headerRow);
            parent.RowDefinitions.Add(contentRow);
            parent.ColumnDefinitions.Add(contentColumn);

            Grid content = new Grid();
            if (descriptor.LayoutItem.IsTextVisible)
            {
                TextBlock header = new TextBlock();
                header.Text = descriptor.LayoutItem.Text;
                Grid.SetRow(header, 0);
                Grid.SetColumn(header, 0);
                parent.Children.Add(header);
            }

            Grid.SetRow(content, 1);
            Grid.SetColumn(content, 0);
            parent.Children.Add(content);

            this.CreateLayoutItemElement(content,
                contentRow,
                contentColumn,
                descriptor);

        }
    }
}
